#include"cond.hpp"
#include <queue>

const int initcount = 5;

using namespace MutexNamespace;
using namespace CondNamespace;


template <class T>
class BlockQueue
{

private:
    bool IsFull()
    {
        return _queue.size() >= _max_cnt;
    }

    bool IsEmpty()
    {
        return _queue.empty();
    }

public:
    BlockQueue(int count = initcount)
        : _max_cnt(count),
          c_pthread_cnt(0),
          p_pthread_cnt(0)
    {
    }

    ~BlockQueue()
    {
    }

    void Equeue(const T &x)
    {

        {
            LockGuard lock(_mutex);
            while (IsFull())
            {
                c_pthread_cnt++;
                std::cout << "生产者休眠，个数：" << c_pthread_cnt << std::endl;
                _full_cond.Wait(_mutex);
                c_pthread_cnt--;
            }
            _queue.push(x);
            if (p_pthread_cnt > 0)
            {
                _emp_cond.Signal();
                std::cout << "唤醒消费者" << std::endl;
            }
        }
    }

    T Pop()
    {
        T ret;
        {
            LockGuard lock(_mutex);
            while (IsEmpty())
            {
                p_pthread_cnt++;
                _emp_cond.Wait(_mutex);
                //std::cout << "消费者休眠，个数：" << p_pthread_cnt << std::endl;
                p_pthread_cnt--;
            }

            ret = _queue.front();
            _queue.pop();

            if (c_pthread_cnt > 0)
            {
                _full_cond.Signal();
                std::cout << "唤醒生产者" << std::endl;
            }
        }

        return ret;
    }

private:
    // 任务队列
    std::queue<T> _queue;
    // 任务队列内最大任务个数
    int _max_cnt;

    // 锁
    Mutex _mutex;
    Cond _full_cond;
    Cond _emp_cond;

    int c_pthread_cnt; // 生产者休眠个数
    int p_pthread_cnt; // 消费者休眠个数
};